#!/usr/bin/perl -w

# vfs-console 1.0
#
# Copyright (c) 2003-04 Tower Technologies s.r.l., All Rights Reserved
#
# Author:	Alessandro Zummo
# License:	GPL

use strict;

use ColdSync;
use ColdSync::SPC;
use ColdSync::SPC::VFS qw(:DEFAULT :vfs_opentags);

use IO::File;
use IO::Socket::INET;

use Data::Dumper;
use File::Basename;

$| = 1;

my $volumes = undef;
my $volume = undef;

StartConduit('sync');

	my $listen_addr = $HEADERS{'addr'} || '127.0.0.1';
	my $listen_port = $HEADERS{'port'} || 12345;

	my $io = new IO::Socket::INET (

		'LocalAddr'	=> $listen_addr,
		'LocalPort'	=> $listen_port,
		'Type'		=> SOCK_STREAM,
		'Listen'	=> 1,
		'Proto'		=> 'tcp',
		'ReuseAddr'	=> 1,
	);

	# Wait for connection

	print "vfs-console: awaiting connection on $listen_addr port $listen_port\n";

	if (defined $io)
	{
		if (my $client = $io->accept)
		{
			print $client "vfs-console 1.0 - Copyright (c) 2003-04 Tower Technologies\n";
			print $client "In case of panic, enter 'help'.\n";

			print $client "vfs> ";

			while (my $cmd = $client->getline)
			{
				my $rc = 0;
				my $arg;

				$cmd =~ s|[\n\r]||g;
				$cmd =~ m|(\w+)(.*)|;

				$cmd = $1;
				$arg = $2;

				$arg =~ s|^(\s+)||;

				print "Got command: -$cmd-\n";
				print "   with arg: -$arg-\n"
					if defined $arg and $arg ne "";

				last if $cmd eq 'quit';

				$rc = cmd_enum($client)		if $cmd eq 'enum';
				$rc = cmd_info($client)		if $cmd eq 'info';
				$rc = cmd_help($client, $arg)	if $cmd eq 'help';
				$rc = cmd_log($client, $arg)	if $cmd eq 'log';
				$rc = cmd_get($client, $arg)	if $cmd eq 'get';
				$rc = cmd_ls($client, $arg)	if $cmd eq 'ls';
				$rc = cmd_rm($client, $arg)	if $cmd eq 'rm';

				print $client "Unknown command '$cmd'.\n"
					if $rc eq 0;

				print $client "vfs> ";
			}
			print $client "goodbye.\n";

			$client->close;
		}
	}
	else
	{
		print "Couldn't create socket: $@\n";
	}

EndConduit();

sub cmd_help
{
	my $client = shift;

	print $client <<EOF;

enum				Enumerate volumes (INVOKE THIS FIRST!)
info				Show volumes info
ls	[path]			List directory contents
get	<file>			Download a file (complete path, please)
put	<file> <vfs path>	Upload a file
rm	<file>			Remove a file
log	some text		Add 'some text' to the HotSync's log	
help				This text	

EOF

	return 1;
}

sub cmd_enum
{
	my $client = shift;

	print $client "Enumerating VFS volumes...\n";
	$volumes = dlp_VFSVolumeEnumerate();
	print $client " found $volumes->{'numVolumes'}.\n";

	# Save first volRef
	$volume = ${$volumes->{'volumes'}}[0];

	return 1;
}

				
sub cmd_info
{
	my $client = shift;

	print $client "\nDumping volume(s) info..\n";

	foreach my $vol ( @{$volumes->{'volumes'}} )
	{
		my $info = dlp_VFSVolumeInfo($vol);
	
		print $client "\nVolume $vol: " . Data::Dumper->Dump( [ $info ] );
	}

	print $client "\n";

	return 1;
}

sub cmd_ls
{
	my $client = shift;
	my $path = shift || '/';

	print $client "VFS[$volume]:$path\n\n";

	my $dirRef = dlp_VFSFileOpen($volume, vfsModeRead, $path);

	if (defined $dirRef)
	{
               	my $dir = dlp_VFSDirEntryEnumerate($dirRef, 0, 10000);

		foreach my $entry ( @{$dir->{'entries'}} )
		{
			print $client " [DIR]"
				if $entry->{'attribute'}{'Directory'}; 

			print $client " $entry->{'name'}\n";
		}		

		dlp_VFSFileClose($dirRef);
	}

	print $client "\n";

	return 1;
}

sub fdump
{
	my ($file, $data) = @_;

	my $fh = new IO::File;

	if ($fh->open(">$file"))
	{
		print $fh $data;

		$fh->close;
	}
}

sub cmd_get
{
	my $client = shift;
	my $path = shift;

	my $fileRef = dlp_VFSFileOpen($volume, vfsModeRead, $path);

	if(defined $fileRef)
	{
		print $client "File opened\n";

		my ($err, $res, $fileSize) = dlp_VFSFileSize($fileRef);

		print $client "Size: $fileSize\n";

		my $data = "";

		# Tested with different values, no real
		# advantage in using a bigger block size.
		my $blockSize = 65536;

		while ($fileSize > 0)
		{
			if ($fileSize < $blockSize)
			{
				$blockSize = $fileSize;
			}

			($err, $res) = dlp_VFSFileRead($fileRef, $blockSize);

			print $client "Read: $res->{'numBytes'}, $fileSize to go.\n";
	
			$data .= $res->{'data'};

			$fileSize -= $blockSize;
		}
		
		dlp_VFSFileClose($fileRef);

		my $outfile = "/tmp/" . fileparse($path);
	
		print $client "Writing to $outfile...\n";

		fdump($outfile, $data);

		print $client "done.\n";
	}

	return 1;
}

sub cmd_rm
{
	my $client = shift;
	my $path = shift;

	print $client "Removing $path...\n";

	dlp_VFSFileDelete($volume, $path);

	print $client "done.\n";

	return 1;
}

sub cmd_log
{
	my $client = shift;
	my $text = shift;

	dlp_AddSyncLogEntry($text);

	print $client "done.\n";

	return 1;
}
